/*
 ***************************************************************************
 * MediaTeK Inc.
 * 4F, No. 2 Technology	5th	Rd.
 * Science-based Industrial	Park
 * Hsin-chu, Taiwan, R.O.C.
 *
 * (c) Copyright 2002-2012, MTK.
 *
 * All rights reserved.	MediaTeK's source	code is	an unpublished work	and	the
 * use of a	copyright notice does not imply	otherwise. This	source code
 * contains	confidential trade secret material of MediaTeK Tech. Any attemp
 * or participation	in deciphering,	decoding, reverse engineering or in	any
 * way altering	the	source code	is stricitly prohibited, unless	the	prior
 * written consent of MediaTeK, Inc. is obtained.
 ***************************************************************************

	Module Name:
	ctc_ME_func.c
	
	Abstract:

	Revision History:
	Who			When			What
	--------	----------		----------------------------------------------
	Name		Date			Modification logs
	kenny.weng		2012/7/16	Create
*/
#include <string.h>
#include "omci_adpt_common.h"
#include "omci_adpt_general.h"
#include "omci_me_ctc.h"
#include "omci_lib_internal.h"

uint8_t AuthStatusFlag = 0;

int getOperatorIDValue(omci_me_info_ptr me_info, omci_attr_dscp_ptr omci_attr);
int getCtcLOIDValue(omci_me_info_ptr me_info, omci_attr_dscp_ptr omci_attr);
int getCtcPasswordValue(omci_me_info_ptr me_info, omci_attr_dscp_ptr omci_attr);
int setAuthStatusValue(omci_me_info_ptr me_info, omci_attr_dscp_ptr omci_attr);
int getLoopDectOperatorIDValue(omci_me_info_ptr me_info, omci_attr_dscp_ptr omci_attr);
int setLoopDectMagt(omci_me_info_ptr me_info, omci_attr_dscp_ptr omci_attr);
int setLoopedPortDown(omci_me_info_ptr me_info, omci_attr_dscp_ptr omci_attr);
int setLoopDectMsgFreq(omci_me_info_ptr me_info, omci_attr_dscp_ptr omci_attr);
int setLoopRecvInterval(omci_me_info_ptr me_info, omci_attr_dscp_ptr omci_attr);
int setPortAndVlanTbl(omci_me_info_ptr me_info, omci_attr_dscp_ptr omci_attr);

extern int setMOPMulticastVersionValue(omci_me_info_ptr me_info, omci_attr_dscp_ptr omci_attr);
extern int setMOPMulticastFuncValue(omci_me_info_ptr me_info, omci_attr_dscp_ptr omci_attr);
extern int setMOPMulticastFastLeaveValue(omci_me_info_ptr me_info, omci_attr_dscp_ptr omci_attr);
extern int setMOPMulticastUpstreamTCIValue(omci_me_info_ptr me_info, omci_attr_dscp_ptr omci_attr);
extern int setMOPMulticastTagCtrlValue(omci_me_info_ptr me_info, omci_attr_dscp_ptr omci_attr);
extern int setMOPMulticastUpstreamRateValue(omci_me_info_ptr me_info, omci_attr_dscp_ptr omci_attr);
int setEMOPMulticastDynamicAclTableValue(omci_me_info_ptr me_info, omci_attr_dscp_ptr omci_attr);
int setEMOPMulticastStaticAclTableValue(omci_me_info_ptr me_info, omci_attr_dscp_ptr omci_attr);
extern int setMOPMulticastRobustnessValue(omci_me_info_ptr me_info, omci_attr_dscp_ptr omci_attr);
extern int setMOPMulticastQuerierIPAddressValue(omci_me_info_ptr me_info, omci_attr_dscp_ptr omci_attr);
extern int setMOPMulticastQueryIntervalValue(omci_me_info_ptr me_info, omci_attr_dscp_ptr omci_attr);
extern int setMOPMulticastQueryMaxResponseTimeValue(omci_me_info_ptr me_info, omci_attr_dscp_ptr omci_attr);
extern int setMOPMulticastLastMemberQueryIntervalValue(omci_me_info_ptr me_info, omci_attr_dscp_ptr omci_attr);
extern int setMOPMulticastUnauthorizedJoinRequestValue(omci_me_info_ptr me_info, omci_attr_dscp_ptr omci_attr);
extern int setMOPMulticastDownstreamIGMPAndTCIValue(omci_me_info_ptr me_info, omci_attr_dscp_ptr omci_attr);
extern int omci_me_multicast_pro_delete_op(management_entry_ptr me_entry, omci_me_info_ptr me_info);

/*******************************************************************************************************************************
CTC LOOP DETECTION

********************************************************************************************************************************/
static attribute_func_t setgetLoopDetectOperatorId = {
	getLoopDectOperatorIDValue,
	NULL,
};

static attribute_func_t setgetLoopDectMagt = {
	NULL,
	setLoopDectMagt,
};

static attribute_func_t setgetLoopedPortDown = {
	NULL,
	setLoopedPortDown,
};

static attribute_func_t setgetLoopDectMsgFreq = {
	NULL,
	setLoopDectMsgFreq,
};

static attribute_func_t setgetLoopRecvInterval = {
	NULL,
	setLoopRecvInterval,
};

static attribute_func_t setgetPortAndVlanTbl = {
	NULL,
	setPortAndVlanTbl,
};

omci_attr_dscp_t omci_attr_ctc_loop_detect_op[]={
{0, "meId" ,					2 , 	ATTR_ACCESS_R,		ATTR_FORMAT_UNSIGNED_INT,	 ATTR_FULLY_SUPPORT,&generalAttrFunc},
{1, "Operator ID" , 			4 , 	ATTR_ACCESS_R,		ATTR_FORMAT_STRING, 		 ATTR_FULLY_SUPPORT,&setgetLoopDetectOperatorId},
{2, "Loop Detection Management",2 ,	    ATTR_ACCESS_R_W,	ATTR_FORMAT_ENUM, 		     ATTR_FULLY_SUPPORT,&setgetLoopDectMagt},
{3, "Looped Port Down", 		2 ,	    ATTR_ACCESS_R_W,	ATTR_FORMAT_ENUM, 		     ATTR_FULLY_SUPPORT,&setgetLoopedPortDown},
{4, "Loop Dect Msg freq",	    2 , 	ATTR_ACCESS_R_W,	ATTR_FORMAT_UNSIGNED_INT,	 ATTR_FULLY_SUPPORT,&setgetLoopDectMsgFreq},
{5, "Loop Recv Interval",		2 , 	ATTR_ACCESS_R_W,	ATTR_FORMAT_UNSIGNED_INT,	 ATTR_FULLY_SUPPORT,&setgetLoopRecvInterval},
{6, "Port and VLAN table",		7 , 	ATTR_ACCESS_R_W,	ATTR_FORMAT_TABLE,	         ATTR_FULLY_SUPPORT,&setgetPortAndVlanTbl},

{255, "" ,						0 , 	0,	0,	0,	NULL}
};

omci_me_func_t omci_me_ctc_loop_detect_op ={
	NULL,
	NULL,
	omci_me_general_set_op,
	omci_me_general_get_op,
};

omci_ctc_loop_detect_t omci_ctc_loop_detect_attr_data = {0};

omci_attr_t omci_ctc_loop_detect_attr={
	(uint8_t *)&omci_ctc_loop_detect_attr_data,
	sizeof(omci_ctc_loop_detect_attr_data),
};

/*******************************************************************************************************************************

CTC LOID authentication

********************************************************************************************************************************/
static attribute_func_t operatorIDGetFunc = {
	getOperatorIDValue,
	NULL,
};

static attribute_func_t ctcLOIDGetFunc = {
	getCtcLOIDValue,
	NULL,
};

static attribute_func_t ctcPasswordGetFunc = {
	getCtcPasswordValue,
	NULL,
};


static attribute_func_t authStatusGetSetFunc = {
	NULL,
	setAuthStatusValue,
};


omci_attr_dscp_t omci_attr_ctc_loid_auth_op[]={
{0, "meId" , 					2 ,     ATTR_ACCESS_R,      ATTR_FORMAT_UNSIGNED_INT,    ATTR_FULLY_SUPPORT,&generalAttrFunc},
{1, "Operator ID" , 			4 ,     ATTR_ACCESS_R,      ATTR_FORMAT_STRING,          ATTR_FULLY_SUPPORT,&operatorIDGetFunc},
{2, "LOID",						24 ,    ATTR_ACCESS_R,      ATTR_FORMAT_STRING,          ATTR_FULLY_SUPPORT,&ctcLOIDGetFunc},
{3, "Password",					12 ,    ATTR_ACCESS_R,      ATTR_FORMAT_STRING,          ATTR_FULLY_SUPPORT,&ctcPasswordGetFunc},
{4, "Authentication status",	1 ,     ATTR_ACCESS_R_W,    ATTR_FORMAT_UNSIGNED_INT,    ATTR_FULLY_SUPPORT,&authStatusGetSetFunc},
{255, "" , 						0 ,		0,  0,  0,	NULL}
};

omci_me_func_t omci_me_ctc_loid_auth_op ={
	omci_me_general_create_op,
	omci_me_general_delete_op,
	omci_me_general_set_op,
	omci_me_general_get_op,
};

omci_ctc_loid_auth_t omci_ctc_loid_auth_attr_data = {0};

omci_attr_t omci_ctc_loid_auth_attr={
	(uint8_t *)&omci_ctc_loid_auth_attr_data,
	sizeof(omci_ctc_loid_auth_attr_data),
};

/*******************************************************************************************************************************
CTC Loop Detection
********************************************************************************************************************************/
int getLoopDectOperatorIDValue(omci_me_info_ptr me_info, omci_attr_dscp_ptr omci_attr)
{
	int ret = -1;
	omci_ctc_loop_detect_ptr ctc_loop_detect_attr = NULL;
	
	omcidbgPrintf(OMCI_DEBUG_LEVEL_TRACE, "Enter %s [%d]\n",__FUNCTION__,__LINE__);
    if((NULL == me_info)||(NULL == omci_attr)){
        omcidbgPrintf(OMCI_DEBUG_LEVEL_ERROR, " %s [%d] parameter is NULL, fail\n",__FUNCTION__,__LINE__);
        ret = -1;
        goto end;
    }
	ctc_loop_detect_attr = (omci_ctc_loop_detect_ptr)me_info->attributes;
    if(ctc_loop_detect_attr == NULL ){
        omcidbgPrintf(OMCI_DEBUG_LEVEL_ERROR, " %s [%d] attributes is NULL, fail\n",__FUNCTION__,__LINE__);
        ret = -1;
        goto end;
    }

	ret = omci_lib_get_operator_id_auth(ctc_loop_detect_attr->operatorId,sizeof(ctc_loop_detect_attr->operatorId));
end:	
	return ret;	
}
int setLoopDectMagt(omci_me_info_ptr me_info, omci_attr_dscp_ptr omci_attr)
{
	int ret = -1;
	omci_ctc_loop_detect_ptr ctc_loop_detect_attr = NULL;
	uint16_t LoopDectMagt_tmp = 0;
	
	omcidbgPrintf(OMCI_DEBUG_LEVEL_TRACE, "Enter %s [%d]\n",__FUNCTION__,__LINE__);
    if((NULL == me_info)||(NULL == omci_attr)){
        omcidbgPrintf(OMCI_DEBUG_LEVEL_ERROR, " %s [%d] parameter is NULL, fail\n",__FUNCTION__,__LINE__);
        ret = -1;
        goto end;
    }
	ctc_loop_detect_attr = (omci_ctc_loop_detect_ptr)me_info->attributes;
    if(ctc_loop_detect_attr == NULL ){
        omcidbgPrintf(OMCI_DEBUG_LEVEL_ERROR, " %s [%d] attributes is NULL, fail\n",__FUNCTION__,__LINE__);
        ret = -1;
        goto end;
    }

	LoopDectMagt_tmp = ctc_loop_detect_attr->LoopDectMagt;
	if(LoopDectMagt_tmp == LOOP_DETECT_MANAGEMENT_INACTIVED)//UNI loop detection management inactivated
	{
		ret = setPortLoopDetect(PORT_ALL,LOOP_DETECT_MANAGEMENT_INACTIVED);
		if(ret != 0)
		{
			omcidbgPrintf(OMCI_DEBUG_LEVEL_ERROR, " %s [%d] setPortLoopDetect, fail\n",__FUNCTION__,__LINE__);
		}
	}
	else if (LoopDectMagt_tmp == LOOP_DETECT_MANAGEMENT_ACTIVED)
	{
		ret = setPortLoopDetect(PORT_ALL,LOOP_DETECT_MANAGEMENT_ACTIVED);
		if(ret != 0)
		{
			omcidbgPrintf(OMCI_DEBUG_LEVEL_ERROR, " %s [%d] setPortLoopDetect, fail\n",__FUNCTION__,__LINE__);
		}
	}
	else
	{
		ret = 0;
	}
end:	
	return ret; 

}	
int setLoopedPortDown(omci_me_info_ptr me_info, omci_attr_dscp_ptr omci_attr)
{
	int ret = -1;
	omci_ctc_loop_detect_ptr ctc_loop_detect_attr = NULL;
	uint16_t LoopPortDown_tmp = 0;
	
	omcidbgPrintf(OMCI_DEBUG_LEVEL_TRACE, "Enter %s [%d]\n",__FUNCTION__,__LINE__);
    if((NULL == me_info)||(NULL == omci_attr)){
        omcidbgPrintf(OMCI_DEBUG_LEVEL_ERROR, " %s [%d] parameter is NULL, fail\n",__FUNCTION__,__LINE__);
        ret = -1;
        goto end;
    }
	ctc_loop_detect_attr = (omci_ctc_loop_detect_ptr)me_info->attributes;
    if(ctc_loop_detect_attr == NULL ){
        omcidbgPrintf(OMCI_DEBUG_LEVEL_ERROR, " %s [%d] attributes is NULL, fail\n",__FUNCTION__,__LINE__);
        ret = -1;
        goto end;
    }

	LoopPortDown_tmp = ctc_loop_detect_attr->LoopPortDown;
	if(LoopPortDown_tmp == LOOP_DETECT_NO_AUTO_PORT_DOWN)//UNI loop detection management inactivated
	{
		ret = setPortDisableLooped(PORT_ALL,LOOP_DETECT_NO_AUTO_PORT_DOWN);
		
		if(ret != 0)
		{
			omcidbgPrintf(OMCI_DEBUG_LEVEL_ERROR, " %s [%d] setPortDisableLooped, fail\n",__FUNCTION__,__LINE__);
		}
	}
	else if (LoopPortDown_tmp == LOOP_DETECT_AUTO_PORT_DOWN)
	{
		ret = setPortDisableLooped(PORT_ALL,LOOP_DETECT_AUTO_PORT_DOWN);
		
		if(ret != 0)
		{
			omcidbgPrintf(OMCI_DEBUG_LEVEL_ERROR, " %s [%d] setPortDisableLooped, fail\n",__FUNCTION__,__LINE__);
		}
	}
	else
	{
		ret = 0;
	}
end:	
	return ret; 
}
int setLoopDectMsgFreq(omci_me_info_ptr me_info, omci_attr_dscp_ptr omci_attr)
{
	int ret = -1;
	omci_ctc_loop_detect_ptr ctc_loop_detect_attr = NULL;
	uint16_t LoopDectMsgFreq_tmp = 0;
	
	omcidbgPrintf(OMCI_DEBUG_LEVEL_TRACE, "Enter %s [%d]\n",__FUNCTION__,__LINE__);
	if((NULL == me_info)||(NULL == omci_attr)){
		omcidbgPrintf(OMCI_DEBUG_LEVEL_ERROR, " %s [%d] parameter is NULL, fail\n",__FUNCTION__,__LINE__);
		ret = -1;
		goto end;
	}
	ctc_loop_detect_attr = (omci_ctc_loop_detect_ptr)me_info->attributes;
	if(ctc_loop_detect_attr == NULL ){
		omcidbgPrintf(OMCI_DEBUG_LEVEL_ERROR, " %s [%d] attributes is NULL, fail\n",__FUNCTION__,__LINE__);
		ret = -1;
		goto end;
	}

	LoopDectMsgFreq_tmp = ctc_loop_detect_attr->LoopDectMsgFreq;
	ret = gponmgr_lib_set_loop_detect_msg_freq(LoopDectMsgFreq_tmp);
	if(ret != 0)
	{
		omcidbgPrintf(OMCI_DEBUG_LEVEL_ERROR, " %s [%d] set_loop_detect_msg_freq, fail\n",__FUNCTION__,__LINE__);
	}
end:	
	return ret; 	
}
int setLoopRecvInterval(omci_me_info_ptr me_info, omci_attr_dscp_ptr omci_attr)
{
	
	int ret = -1;
	omci_ctc_loop_detect_ptr ctc_loop_detect_attr = NULL;
	uint16_t LoopRecvInterval_tmp = 0;
	
	omcidbgPrintf(OMCI_DEBUG_LEVEL_TRACE, "Enter %s [%d]\n",__FUNCTION__,__LINE__);
	if((NULL == me_info)||(NULL == omci_attr)){
		omcidbgPrintf(OMCI_DEBUG_LEVEL_ERROR, " %s [%d] parameter is NULL, fail\n",__FUNCTION__,__LINE__);
		ret = -1;
		goto end;
	}
	ctc_loop_detect_attr = (omci_ctc_loop_detect_ptr)me_info->attributes;
	if(ctc_loop_detect_attr == NULL ){
		omcidbgPrintf(OMCI_DEBUG_LEVEL_ERROR, " %s [%d] attributes is NULL, fail\n",__FUNCTION__,__LINE__);
		ret = -1;
		goto end;
	}

	LoopRecvInterval_tmp = ctc_loop_detect_attr->LoopRecvInterval;
	ret = gponmgr_lib_set_loop_Recv_Interval(LoopRecvInterval_tmp);
	if(ret != 0)
	{
		omcidbgPrintf(OMCI_DEBUG_LEVEL_ERROR, " %s [%d] set_loop_Recv_Interval, fail\n",__FUNCTION__,__LINE__);
	}
end:	
	return ret; 	
}
int setPortAndVlanTbl(omci_me_info_ptr me_info, omci_attr_dscp_ptr omci_attr)
{
	return 0;
}

/*******************************************************************************************************************************
CTC Extended multicast operations profiles

********************************************************************************************************************************/
static attribute_func_t EMOPMulticastVersionGetSetFunc = {
	NULL,
	setMOPMulticastVersionValue,
};

static attribute_func_t EMOPMulticastFuncGetSetFunc = {
	NULL,
	setMOPMulticastFuncValue,
};

static attribute_func_t EMOPMulticastFastLeaveGetSetFunc = {
	NULL,
	setMOPMulticastFastLeaveValue,
};

static attribute_func_t EMOPMulticastUpstreamTCIGetSetFunc = {
	NULL,
	setMOPMulticastUpstreamTCIValue,
};

static attribute_func_t EMOPMulticastTagCtrlGetSetFunc = {
	NULL,
	setMOPMulticastTagCtrlValue,
};

static attribute_func_t EMOPMulticastUpstreamRateGetSetFunc = {
	NULL,
	setMOPMulticastUpstreamRateValue,
};

static attribute_func_t EMOPMulticastDynamicAclTableGetSetFunc = {
	NULL,//	getMOPMulticastDynamicAclTableValue, not need in OMCI2.0
	setEMOPMulticastDynamicAclTableValue,
};

static attribute_func_t EMOPMulticastStaticAclTableGetSetFunc = {
	NULL,//	getMOPMulticastStaticAclTableValue, not need in OMCI2.0
	setEMOPMulticastStaticAclTableValue,
}; 

static attribute_func_t EMOPMulticastRobustnessGetSetFunc = {
	NULL,
	setMOPMulticastRobustnessValue,
}; 

static attribute_func_t EMOPMulticastQuerierIPAddressGetSetFunc = {
	NULL,
	setMOPMulticastQuerierIPAddressValue,
}; 

static attribute_func_t EMOPMulticastQueryIntervalGetSetFunc = {
	NULL,
	setMOPMulticastQueryIntervalValue,
}; 

static attribute_func_t EMOPMulticastQueryMaxResponseTimeGetSetFunc = {
	NULL,
	setMOPMulticastQueryMaxResponseTimeValue,
}; 

static attribute_func_t EMOPMulticastLastMemberQueryIntervalGetSetFunc = {
	NULL,
	setMOPMulticastLastMemberQueryIntervalValue,
}; 

static attribute_func_t EMOPMulticastUnauthorizedJoinRequestGetSetFunc = {
	NULL,
	setMOPMulticastUnauthorizedJoinRequestValue,
}; 

static attribute_func_t EMOPMulticastDownstreamIGMPAndTCIGetSetFunc = {
	NULL,
	setMOPMulticastDownstreamIGMPAndTCIValue,
};

omci_attr_dscp_t omci_attr_ctc_ext_multicast_op_profile_op[]={
{0, "meId" , 						2 ,     ATTR_ACCESS_R_SET_CREATE,       ATTR_FORMAT_UNSIGNED_INT,     ATTR_FULLY_SUPPORT,&generalAttrFunc},
{1, "IGMP Version" , 				1 ,     ATTR_ACCESS_R_W_SET_CREATE,     ATTR_FORMAT_UNSIGNED_INT,     ATTR_FULLY_SUPPORT,&EMOPMulticastVersionGetSetFunc},
{2, "IGMP function",				1 ,     ATTR_ACCESS_R_W_SET_CREATE,     ATTR_FORMAT_UNSIGNED_INT,     ATTR_FULLY_SUPPORT,&EMOPMulticastFuncGetSetFunc},
{3, "Immediate leave",				1 ,     ATTR_ACCESS_R_W_SET_CREATE,     ATTR_FORMAT_UNSIGNED_INT,     ATTR_FULLY_SUPPORT,&EMOPMulticastFastLeaveGetSetFunc},
{4, "Upstream IGMP TCI",			2 ,     ATTR_ACCESS_R_W_SET_CREATE,     ATTR_FORMAT_UNSIGNED_INT,     ATTR_FULLY_SUPPORT,&EMOPMulticastUpstreamTCIGetSetFunc},
{5, "Upstream IGMP tag control",	1 ,     ATTR_ACCESS_R_W_SET_CREATE,     ATTR_FORMAT_UNSIGNED_INT,     ATTR_FULLY_SUPPORT,&EMOPMulticastTagCtrlGetSetFunc},
{6, "Upstream IGMP rate",			4 ,     ATTR_ACCESS_R_W_SET_CREATE,     ATTR_FORMAT_UNSIGNED_INT,     ATTR_FULLY_SUPPORT,&EMOPMulticastUpstreamRateGetSetFunc},
{7, "Dynamic ACL table",			30 ,    ATTR_ACCESS_R_W,                ATTR_FORMAT_TABLE,            ATTR_FULLY_SUPPORT,&EMOPMulticastDynamicAclTableGetSetFunc},
{8, "Static ACL table",				30 ,    ATTR_ACCESS_R_W,                ATTR_FORMAT_TABLE,            ATTR_FULLY_SUPPORT,&EMOPMulticastStaticAclTableGetSetFunc},
{9, "Lost groups list table",		16 ,    ATTR_ACCESS_R,                  ATTR_FORMAT_TABLE,            ATTR_FULLY_SUPPORT,&generalAttrFunc},
{10, "Robustness",					1 ,     ATTR_ACCESS_R_W_SET_CREATE,     ATTR_FORMAT_UNSIGNED_INT,     ATTR_FULLY_SUPPORT,&EMOPMulticastRobustnessGetSetFunc},
{11, "Querier IP address",			16 ,    ATTR_ACCESS_R_W,                ATTR_FORMAT_STRING,           ATTR_FULLY_SUPPORT,&EMOPMulticastQuerierIPAddressGetSetFunc},
{12, "Querier interval",			4 ,     ATTR_ACCESS_R_W_SET_CREATE,     ATTR_FORMAT_UNSIGNED_INT,     ATTR_FULLY_SUPPORT,&EMOPMulticastQueryIntervalGetSetFunc},
{13, "Querier max response time",	4 ,     ATTR_ACCESS_R_W_SET_CREATE,     ATTR_FORMAT_UNSIGNED_INT,     ATTR_FULLY_SUPPORT,&EMOPMulticastQueryMaxResponseTimeGetSetFunc},
{14, "Last member query interval",	4 ,     ATTR_ACCESS_R_W,                ATTR_FORMAT_UNSIGNED_INT,     ATTR_FULLY_SUPPORT,&EMOPMulticastLastMemberQueryIntervalGetSetFunc},
{15, "Unauthorized join request",	1 ,     ATTR_ACCESS_R_W,                ATTR_FORMAT_UNSIGNED_INT,     ATTR_FULLY_SUPPORT,&EMOPMulticastUnauthorizedJoinRequestGetSetFunc},
{16, "Downstream IGMP TCI",			3 ,     ATTR_ACCESS_R_W_SET_CREATE,     ATTR_FORMAT_STRING,       	 ATTR_FULLY_SUPPORT,&EMOPMulticastDownstreamIGMPAndTCIGetSetFunc},
{255, "" ,							0 ,		0 ,0 ,0 ,NULL}
};

omci_me_func_t omci_me_ctc_ext_multicast_op_profile_op ={
	omci_me_general_create_op,
	omci_me_multicast_pro_delete_op,
	omci_me_general_set_op,
	omci_me_general_get_op,
};

omci_ctc_ext_multicast_op_profile_t omci_ctc_ext_multicast_op_profile_attr_data = {0};

omci_attr_t omci_ctc_ext_multicast_op_profile_attr={
	(uint8_t *)&omci_ctc_ext_multicast_op_profile_attr_data,
	sizeof(omci_ctc_ext_multicast_op_profile_attr_data),
};


/*******************************************************************************************************************************
CTC LOID authentication

********************************************************************************************************************************/

int getOperatorIDValue(omci_me_info_ptr me_info, omci_attr_dscp_ptr omci_attr)
{
	int ret = -1;
	omci_ctc_loid_auth_ptr ctc_loid_auth_attr = NULL;
	
	omcidbgPrintf(OMCI_DEBUG_LEVEL_TRACE, "Enter %s [%d]\n",__FUNCTION__,__LINE__);
    if((NULL == me_info)||(NULL == omci_attr)){
        omcidbgPrintf(OMCI_DEBUG_LEVEL_ERROR, " %s [%d] parameter is NULL, fail\n",__FUNCTION__,__LINE__);
        ret = -1;
        goto end;
    }
	ctc_loid_auth_attr = (omci_ctc_loid_auth_ptr)me_info->attributes;
    if(ctc_loid_auth_attr == NULL ){
        omcidbgPrintf(OMCI_DEBUG_LEVEL_ERROR, " %s [%d] attributes is NULL, fail\n",__FUNCTION__,__LINE__);
        ret = -1;
        goto end;
    }

	ret = omci_lib_get_operator_id_auth(ctc_loid_auth_attr->operatorId,OMCI_OPERATOR_ID_LENS);
end:	
	return ret;	
}

int getCtcLOIDValue(omci_me_info_ptr me_info, omci_attr_dscp_ptr omci_attr)
{
	int ret = -1;
	omci_ctc_loid_auth_ptr ctc_loid_auth_attr = NULL;
	
	omcidbgPrintf(OMCI_DEBUG_LEVEL_TRACE, "Enter %s [%d]\n",__FUNCTION__,__LINE__);
    if((NULL == me_info)||(NULL == omci_attr)){
        omcidbgPrintf(OMCI_DEBUG_LEVEL_ERROR, " %s [%d] parameter is NULL, fail\n",__FUNCTION__,__LINE__);
        ret = -1;
        goto end;
    }
	ctc_loid_auth_attr = (omci_ctc_loid_auth_ptr)me_info->attributes;
    if(ctc_loid_auth_attr == NULL ){
        omcidbgPrintf(OMCI_DEBUG_LEVEL_ERROR, " %s [%d] attributes is NULL, fail\n",__FUNCTION__,__LINE__);
        ret = -1;
        goto end;
    }

	ret = omci_lib_get_loid(ctc_loid_auth_attr->loid,OMCI_LOID_LENS);
	omcidbgPrintf(OMCI_DEBUG_LEVEL_TRACE, "Enter %s [%d], LOID = %s\n",__FUNCTION__,__LINE__, ctc_loid_auth_attr->loid);
end:	
	return ret;	
}

int getCtcPasswordValue(omci_me_info_ptr me_info, omci_attr_dscp_ptr omci_attr)
{
	int ret = -1;
	omci_ctc_loid_auth_ptr ctc_loid_auth_attr = NULL;
	
	omcidbgPrintf(OMCI_DEBUG_LEVEL_TRACE, "Enter %s [%d]\n",__FUNCTION__,__LINE__);
    if((NULL == me_info)||(NULL == omci_attr)){
        omcidbgPrintf(OMCI_DEBUG_LEVEL_ERROR, " %s [%d] parameter is NULL, fail\n",__FUNCTION__,__LINE__);
        ret = -1;
        goto end;
    }
	ctc_loid_auth_attr = (omci_ctc_loid_auth_ptr)me_info->attributes;
    if(ctc_loid_auth_attr == NULL ){
        omcidbgPrintf(OMCI_DEBUG_LEVEL_ERROR, " %s [%d] attributes is NULL, fail\n",__FUNCTION__,__LINE__);
        ret = -1;
        goto end;
    }

	ret = omci_lib_get_loid_password(ctc_loid_auth_attr->password,OMCI_LOID_PASSWORD_LENS);
end:	
	return ret;	
}

int setAuthStatusValue(omci_me_info_ptr me_info, omci_attr_dscp_ptr omci_attr)
{
	int ret = -1;
	omci_ctc_loid_auth_ptr ctc_loid_auth_attr = NULL;
	char entryValue[8]={0};

	/*set AuthStatus to instance and romfile*/
	
	omcidbgPrintf(OMCI_DEBUG_LEVEL_TRACE, "Enter %s [%d]\n",__FUNCTION__,__LINE__);
    if((NULL == me_info)||(NULL == omci_attr)){
        omcidbgPrintf(OMCI_DEBUG_LEVEL_ERROR, " %s [%d] parameter is NULL, fail\n",__FUNCTION__,__LINE__);
		return -1;
    }
	ctc_loid_auth_attr = (omci_ctc_loid_auth_ptr)me_info->attributes;
    if(ctc_loid_auth_attr == NULL ){
        omcidbgPrintf(OMCI_DEBUG_LEVEL_ERROR, " %s [%d] attributes is NULL, fail\n",__FUNCTION__,__LINE__);
		return -1;
    }
			
	if(0 != ctc_loid_auth_attr->authStatus){
		AuthStatusFlag = 1;
	}
	ret = omci_lib_set_auth_status(ctc_loid_auth_attr->authStatus);
	if(0 != ret){
        omcidbgPrintf(OMCI_DEBUG_LEVEL_ERROR, " %s [%d] omci_lib_set_auth_status fail\n",__FUNCTION__,__LINE__);
		return ret;
	}
	sprintf(entryValue, "%d", ctc_loid_auth_attr->authStatus);
	ret = omci_tcapi_set("GPON_LOIDAuth","AuthStatus",entryValue);
	if(0 != ret){
        omcidbgPrintf(OMCI_DEBUG_LEVEL_ERROR, " %s [%d] tcapi set AuthStatus fail\n",__FUNCTION__,__LINE__);
		return ret;
	}
	return 0;
}

/*******************************************************************************************************************************
CTC Extended multicast operations profiles

********************************************************************************************************************************/

/*******************************************************************************************
**function name
	setEMOPMulticastAclTableValueByType
**description:
	Set ACL Value for OLT request according to the attribute index.
 **retrun :
 	-1:	failure
 	0:	success
**parameter:
  	value :	return value
  	meInstantPtr: 9.3.27 instance pointer
  	omciAttribute: 9.3.27 attribute pointer
  	attrIndex: valid value
  		7: dynamic acl attribute
  		8: static acl attribute
********************************************************************************************/
static int setEMOPMulticastAclTableValueByType(omci_me_info_ptr me_info, omci_attr_dscp_ptr omci_attr, IN uint16_t attrIndex){
	uint8_t *tmp_ptr = NULL;
	uint8_t action = 0;//0:remove this entry, 1:add this entry, 2: clear table
	uint16_t instanceId = 0;//instance id
	uint32_t tableSize = 0;
	uint32_t length = 0;
	uint8_t findFlag = 0;//0:not find, 1:find
	int ret = -1;
	uint16_t ctrlField = 0;
	uint8_t setCtrl = 0;
	uint8_t rowPart = 0;
	uint16_t rowID = 0;
	uint16_t ctrlField_tmp = 0;
	uint8_t rowPart_tmp = 0;
	uint16_t rowID_tmp = 0;	
	omciIgmpRuleInfo_t ruleRecordInfo;
	omciIgmpRuleInfo_ptr ruleRecord = &ruleRecordInfo;
	uint16_t type = 0;
	uint16_t ruleType = 0;
	uint8_t tempAclTableRowEntry[OMCI_EMOP_ACL_TABLE_ROW_ENTRY_LENGTH] = {0};
	uint8_t zero[OMCI_EMOP_ACL_TABLE_ROW_ENTRY_LENGTH] = {0};
	omci_multicast_op_profile_ptr multicast_op_attr = NULL;
	omci_me_info_t old_me = {0};
	omci_multicast_op_profile_ptr multicast_op_attr_old = NULL;
	
	omcidbgPrintf(OMCI_DEBUG_LEVEL_TRACE, "[%5d][%s]start, attrIndex =%02x\n",__LINE__, __func__, attrIndex);

    if((NULL == me_info)||(NULL == omci_attr)){
        omcidbgPrintf(OMCI_DEBUG_LEVEL_ERROR, " %s [%d] parameter is NULL, fail\n",__FUNCTION__,__LINE__);
        ret = -1;
        goto end;
    }
	
	multicast_op_attr = (omci_multicast_op_profile_ptr)me_info->attributes;
    if(multicast_op_attr == NULL ){
        omcidbgPrintf(OMCI_DEBUG_LEVEL_ERROR, " %s [%d] attributes is NULL, fail\n",__FUNCTION__,__LINE__);
        ret = -1;
        goto end;
    }
	
	/*only support dynamic acl attribute or static acl attribute*/
	if(attrIndex == OMCI_MULTICAST_DYNAMIC_ACL_ATTR_INDEX){
		ruleType = OMCI_MULTICAST_IGMP_RULE_TYPE_DYN;
		type = OMCI_MULTICAST_DYNAMIC_ACL_TYPE;
	}else if(attrIndex == OMCI_MULTICAST_STATIC_ACL_ATTR_INDEX){
		ruleType = OMCI_MULTICAST_IGMP_RULE_TYPE_STATIC;
		type = OMCI_MULTICAST_STATIC_ACL_TYPE;		
	}else{
		ret = -1;
		omcidbgPrintf(OMCI_DEBUG_LEVEL_ERROR, "[%5d][%s]attrIndex fail\n",__LINE__, __func__);
		goto end;
	}

	/*parse value*/
	tmp_ptr = (uint8_t *)multicast_op_attr->dynAccessCtrlListTable.buf;
	ctrlField = get16(tmp_ptr);
	setCtrl = ((ctrlField & OMCI_EMOP_ACL_TABLE_ENTRY_SET_CTRL_MASK) >> OMCI_EMOP_ACL_TABLE_ENTRY_SET_CTRL_FILED);
	rowPart = ((ctrlField & OMCI_EMOP_ACL_TABLE_ENTRY_ROW_PART_MASK) >> OMCI_EMOP_ACL_TABLE_ENTRY_ROW_PART_FILED);
	rowID = (ctrlField & OMCI_EMOP_ACL_TABLE_ENTRY_ROW_ID_MASK);	
	omcidbgPrintf(OMCI_DEBUG_LEVEL_TRACE, "[%5d][%s]setCtrl=0x%2x, rowPart=0x%2x, rowID=%d\n",__LINE__, __func__, setCtrl,rowPart,rowID);

	/*set rule from packet value */
	memset(ruleRecord, 0, sizeof(omciIgmpRuleInfo_t));
	ruleRecord->rowKey = rowID;
	ruleRecord->ruleType = ruleType;

	
	/*get instance id*/
	instanceId = me_info->inst_id;

	old_me.class_id = me_info->class_id;
	old_me.inst_id = me_info->inst_id;
	old_me.mask = OMCI_MULTICAST_DYNAMIC_ACL_TYPE;
	
	if(omci_attr_get_one_table_attr_by_mask(&old_me) != 0){
		omcidbgPrintf(OMCI_DEBUG_LEVEL_ERROR, "[%s][%d]get data failed.\n",__FUNCTION__,__LINE__);
		ret = -1;
		goto end;
	}		
	/*get current setting table entry. */
	multicast_op_attr_old = (omci_multicast_op_profile_ptr)old_me.attributes;  
	if(multicast_op_attr_old == NULL){
		omcidbgPrintf(OMCI_DEBUG_LEVEL_ERROR, " %s [%d] attributes is NULL, fail\n",__FUNCTION__,__LINE__);
		ret = -1;
		goto end;
	}
	/*get current table content*/
	tableSize = multicast_op_attr_old->dynAccessCtrlListTable.len;
	tmp_ptr = (uint8_t *)multicast_op_attr_old->dynAccessCtrlListTable.buf;

	/*get action(add/del/clear)*/
	action = setCtrl;	
	if(action == OMCI_IGMP_ACL_TABLE_ENTRY_DEL_ACTION){// delete table
		/*search record*/
		length = OMCI_EMOP_ACL_TABLE_ROW_ENTRY_LENGTH;
		while( tmp_ptr != NULL){
			ctrlField_tmp = get16(tmp_ptr+OMCI_EMOP_ACL_TABLE_ENTRY_LENGTH*rowPart);
			rowPart_tmp = ((ctrlField_tmp & OMCI_EMOP_ACL_TABLE_ENTRY_ROW_PART_MASK)>> OMCI_EMOP_ACL_TABLE_ENTRY_ROW_PART_FILED);
			rowID_tmp = (ctrlField_tmp & OMCI_EMOP_ACL_TABLE_ENTRY_ROW_ID_MASK);	
			if((rowID == rowID_tmp) &&(rowPart == rowPart_tmp)){
				memset(tmp_ptr + OMCI_EMOP_ACL_TABLE_ENTRY_LENGTH*rowPart, 0, OMCI_EMOP_ACL_TABLE_ENTRY_LENGTH);				
				memcpy(tempAclTableRowEntry, tmp_ptr, OMCI_EMOP_ACL_TABLE_ROW_ENTRY_LENGTH);
				findFlag = 1;//find
				break;
			}

			length += OMCI_EMOP_ACL_TABLE_ROW_ENTRY_LENGTH;
			if(length > multicast_op_attr_old->dynAccessCtrlListTable.len){ 
				omcidbgPrintf(OMCI_DEBUG_LEVEL_TRACE, "[%5d][%s]length:%d > multicast_op_attr_old->dynAccessCtrlListTable.len:%d\n",
					__LINE__, __func__, length, multicast_op_attr_old->dynAccessCtrlListTable.len);
				findFlag = 0;//not find
				break;
			}
			tmp_ptr += OMCI_EMOP_ACL_TABLE_ROW_ENTRY_LENGTH; 
		}
		
		/*get real length*/
		length -= OMCI_EMOP_ACL_TABLE_ROW_ENTRY_LENGTH;
		/*get valid content in table*/
		if(findFlag == 1){
			if(memcmp(tempAclTableRowEntry, zero, OMCI_EMOP_ACL_TABLE_ROW_ENTRY_LENGTH) == 0){
			/*delete ACL rule via calling multicast API*/
			ret = setRealMulticastRuleByProfile(instanceId, type, action, NULL, ruleRecord);
			if(ret != 0){
				ret = -1;
				omcidbgPrintf(OMCI_DEBUG_LEVEL_ERROR, "[%5d][%s]setRealMulticastRuleByProfile fail\n",__LINE__, __func__);
				goto end;
			}			
			
			/*delete a entry from table list*/			
			/*malloc new space*/
			if(tableSize-OMCI_EMOP_ACL_TABLE_ROW_ENTRY_LENGTH > 0)
			{
				tableSize -= OMCI_EMOP_ACL_TABLE_ROW_ENTRY_LENGTH; //update current table size
			}
				else
				{
					tableSize = 0;
				}				
			}
			else{
				/*set rule  info */
				/*row part 0 */
				tmp_ptr = tempAclTableRowEntry;
				ruleRecord->gemPortId = get16(tmp_ptr+2);
				ruleRecord->vid = get16(tmp_ptr+4);	
				ruleRecord->imputedBandwidth = get32(tmp_ptr+6);
				/*row part 1 */	
				tmp_ptr = tempAclTableRowEntry+OMCI_EMOP_ACL_TABLE_ENTRY_LENGTH;
				if (memcmp(tmp_ptr+2, zero, OMCI_MULTICAST_IPV4_OFFSET) == 0) /* ipv4 address*/		
					memcpy(ruleRecord->startDestIp,tmp_ptr+2+OMCI_MULTICAST_IPV4_OFFSET, OMCI_MULTICAST_IPV4_LEN);
				else
					memcpy(ruleRecord->startDestIp,tmp_ptr+2, OMCI_MULTICAST_IP_LEN);
				/*row part 2 */	
				tmp_ptr = tempAclTableRowEntry+2*OMCI_EMOP_ACL_TABLE_ENTRY_LENGTH;
				if (memcmp(tmp_ptr+2, zero, OMCI_MULTICAST_IPV4_OFFSET) == 0) /* ipv4 address*/		
					memcpy(ruleRecord->endDestIp,tmp_ptr+2+OMCI_MULTICAST_IPV4_OFFSET, OMCI_MULTICAST_IPV4_LEN);
				else
					memcpy(ruleRecord->endDestIp,tmp_ptr+2, OMCI_MULTICAST_IP_LEN);
				omcidbgPrintf(OMCI_DEBUG_LEVEL_TRACE, "[%5d][%s]ruleRecord rowKey:%x,ruleType:%x,gemPortId:%x,vid:%x,srcIp:%x,startDestIp:%x,endDestIp:%x\n",
						__LINE__, __func__, ruleRecord->rowKey,ruleRecord->ruleType,ruleRecord->gemPortId,ruleRecord->vid, 
					get32(ruleRecord->srcIp), get32(ruleRecord->startDestIp), get32(ruleRecord->endDestIp));

				
				/*set ACL rule via calling multicast API*/
				ret = setRealMulticastRuleByProfile(instanceId, type, OMCI_IGMP_ACL_TABLE_ENTRY_WRITE_ACTION, NULL, ruleRecord);
				if(ret != 0){
					ret = -1;
					omcidbgPrintf(OMCI_DEBUG_LEVEL_ERROR, "[%5d][%s]setRealMulticastRuleByProfile fail\n",__LINE__, __func__);
					goto end;
				}			

				omcidbgPrintf(OMCI_DEBUG_LEVEL_TRACE, "[%5d][%s] not last entry, modify this record\n", __LINE__, __func__);			
			}
		}else{
			omcidbgPrintf(OMCI_DEBUG_LEVEL_TRACE, "[%5d][%s] not find \n", __LINE__, __func__);			
		}
	}else if(action == OMCI_IGMP_ACL_TABLE_ENTRY_WRITE_ACTION)// add or modify table
	{
		
		/*search record*/
		while(tmp_ptr != NULL){		
			ctrlField_tmp = get16(tmp_ptr);
			rowID_tmp = (ctrlField_tmp & OMCI_EMOP_ACL_TABLE_ENTRY_ROW_ID_MASK);	
			if(rowID == rowID_tmp){
				memcpy(tempAclTableRowEntry, tmp_ptr, OMCI_EMOP_ACL_TABLE_ROW_ENTRY_LENGTH);
				findFlag = 1;//find
				break;
			}
			length += OMCI_EMOP_ACL_TABLE_ROW_ENTRY_LENGTH;
			if(length > multicast_op_attr_old->dynAccessCtrlListTable.len){
				omcidbgPrintf(OMCI_DEBUG_LEVEL_TRACE, "[%5d][%s]length:%d > multicast_op_attr_old->dynAccessCtrlListTable.len:%d\n",
					__LINE__, __func__, length, multicast_op_attr_old->dynAccessCtrlListTable.len);
				findFlag = 0;//not find
				break;
			}
			tmp_ptr += OMCI_EMOP_ACL_TABLE_ROW_ENTRY_LENGTH;
		}
		/*get real length*/
		length -= OMCI_EMOP_ACL_TABLE_ROW_ENTRY_LENGTH;
		memcpy(tempAclTableRowEntry + OMCI_EMOP_ACL_TABLE_ENTRY_LENGTH*rowPart, 
			(uint8_t *)multicast_op_attr_old->dynAccessCtrlListTable.buf, OMCI_EMOP_ACL_TABLE_ENTRY_LENGTH);

		/*set rule other info */
		/*row part 0 */
		tmp_ptr = tempAclTableRowEntry;
		ruleRecord->gemPortId = get16(tmp_ptr+2);
		ruleRecord->vid = get16(tmp_ptr+4);	
		ruleRecord->imputedBandwidth = get32(tmp_ptr+6);
		/*row part 1 */	
		tmp_ptr = tempAclTableRowEntry+OMCI_EMOP_ACL_TABLE_ENTRY_LENGTH;
		if (memcmp(tmp_ptr+2, zero, OMCI_MULTICAST_IPV4_OFFSET) == 0) /* ipv4 address*/		
			memcpy(ruleRecord->startDestIp,tmp_ptr+2+OMCI_MULTICAST_IPV4_OFFSET, OMCI_MULTICAST_IPV4_LEN);
		else
			memcpy(ruleRecord->startDestIp,tmp_ptr+2, OMCI_MULTICAST_IP_LEN);
		/*row part 2 */	
		tmp_ptr = tempAclTableRowEntry+2*OMCI_EMOP_ACL_TABLE_ENTRY_LENGTH;
		if (memcmp(tmp_ptr+2, zero, OMCI_MULTICAST_IPV4_OFFSET) == 0) /* ipv4 address*/		
			memcpy(ruleRecord->endDestIp,tmp_ptr+2+OMCI_MULTICAST_IPV4_OFFSET, OMCI_MULTICAST_IPV4_LEN);
		else
			memcpy(ruleRecord->endDestIp,tmp_ptr+2, OMCI_MULTICAST_IP_LEN);
		omcidbgPrintf(OMCI_DEBUG_LEVEL_TRACE, "[%5d][%s]ruleRecord rowKey:%x,ruleType:%x,gemPortId:%x,vid:%x,srcIp:%x,startDestIp:%x,endDestIp:%x\n",
				__LINE__, __func__, ruleRecord->rowKey,ruleRecord->ruleType,ruleRecord->gemPortId,ruleRecord->vid, 
			get32(ruleRecord->srcIp), get32(ruleRecord->startDestIp), get32(ruleRecord->endDestIp));

		
		/*set ACL rule via calling multicast API*/
		ret = setRealMulticastRuleByProfile(instanceId, type, action, NULL, ruleRecord);
		if(ret != 0){
			ret = -1;
			omcidbgPrintf(OMCI_DEBUG_LEVEL_ERROR, "[%5d][%s]setRealMulticastRuleByProfile fail\n",__LINE__, __func__);
			goto end;
		}
			
		/*get valid content in table*/
		if(findFlag == 1){
			omcidbgPrintf(OMCI_DEBUG_LEVEL_TRACE, "[%5d][%s] find, modify this record\n", __LINE__, __func__);			
		}else{
			omcidbgPrintf(OMCI_DEBUG_LEVEL_TRACE, "[%5d][%s]not find, add this record\n", __LINE__, __func__);	
			tableSize += OMCI_EMOP_ACL_TABLE_ROW_ENTRY_LENGTH;
		}
	
	}	else if(action == OMCI_IGMP_ACL_TABLE_ENTRY_CLEAR_ACTION){//clear this table
		/*real clean record*/
		ret = clearRealMulticastRuleByProfileType(instanceId, type);		
		if(ret != 0){
			omcidbgPrintf(OMCI_DEBUG_LEVEL_ERROR, "[%5d][%s]clearRealMulticastRuleByProfileType fail\n",__LINE__, __func__);
			goto end;
		}
		tableSize = 0;	
	}

#if 0
	omciDumpTable(tmpValue_ptr, tableSize);
#endif

	ret = 0;
end:

	if(ret != 0){
		ret = -1;
	}

	omcidbgPrintf(OMCI_DEBUG_LEVEL_TRACE, "[%5d][%s]end, tableSize=%d\n",__LINE__, __func__, tableSize);
	return ret;
}



int setEMOPMulticastDynamicAclTableValue(omci_me_info_ptr me_info, omci_attr_dscp_ptr omci_attr)
{
	uint16_t attrIndex = OMCI_MULTICAST_DYNAMIC_ACL_ATTR_INDEX;
	
	return setEMOPMulticastAclTableValueByType(me_info, omci_attr, attrIndex);
}


int setEMOPMulticastStaticAclTableValue(omci_me_info_ptr me_info, omci_attr_dscp_ptr omci_attr)
{
	uint16_t attrIndex = OMCI_MULTICAST_STATIC_ACL_ATTR_INDEX;
	
	return setEMOPMulticastAclTableValueByType(me_info, omci_attr, attrIndex);
}


